from entity import*
from hitbox import*
from platform import*

class player(entity): 
	"""The player, inherits from entity so it has all the properties of entities."""
	def __init__(self, manager):
		entity.__init__(self, manager)
		self.updates = True

		self.rect = pygame.Rect(0,0,40,40) #I am making the player hitbox the same size as the draw rect. I don't fully understand why it should be smaller.
		self.rect.topleft = (50,50)

		self.lhitbox = hitbox(self.rect, -(self.rect.width / 2) - 5,12,10,25)
		self.rhitbox = hitbox(self.rect, +(self.rect.width / 2) + 5,12,10,25)
		self.bhitbox = hitbox(self.rect,0,(self.rect.height / 2) + 5,35,10)
		self.thitbox = hitbox(self.rect,0,-(self.rect.height / 2) + 5,35,10)
		self.toprhitbox = hitbox(self.rect, +(self.rect.width / 2) + 6,-23,10,10)
		self.toplhitbox	= hitbox(self.rect, -(self.rect.width / 2) - 6 ,-23,10,10)

		self.right = False			#'Right' key is held
		self.canmoveright = False	#Player can move right
		self.left = False
		self.canmoveleft = False
		self.canmovedown = False #Replaces self.down
		self.canmoveup = True

		self.jump = False		#Player Presses space
		self.injump = False		#Player is in a jump (moving upward)
		self.holdjump = 0		#Variable that counts upward. Makes sure that if the player holds down space, they will not walljump after jumpin'
		self.hold = False		#Variable that, when true, adds to 'holdjump'
		self.walljumptimer = 0
		self.previouslyJumping = False #If the player was holding the jump button in the last frame.
		self.climbing = False

		self.speed = 0
		self.downforce = 0
		self.jumpforce = 0
		self.dog = 0
		
		self.carrying = 0
		
		self.nocollide = []
		
		#manager.quadtree.insertEntity(self)

	def addlist(self,entity):
		self.nocollide.append(entity)
		
	def update(self, timeElapsed, manager):
		manager.quadtrees[int(self.layer)].removeEntity(self)
		self.move( manager)

		self.right = manager.keysdown['right']
		self.left = manager.keysdown['left']
		self.up = manager.keysdown['up']
		self.down = manager.keysdown['down']
		
		if(manager.keysdown['space']):
			self.hold = True
			self.jump = True
			self.previouslyJumping = True
			if self.injump == False:
				self.jumpforce = 7		#This number is important. It decides how fast the player moves upwards in a jump.
				if (self.carrying != 0):
					self.jumpforce = 7 * self.carrying.mass / manager.fpsupdate
				self.walljumptimer = 0

		if(not manager.keysdown['space'] and self.previouslyJumping == True):
			self.jump = False
			self.hold = False
			self.jumpforce /= 2	/ manager.fpsupdate
			self.previouslyJumping = False #The player was not holding the jump key in the last frame.

		#These lines get entities near the hitboxes specified.
		entitiesnearby = manager.getEntitiesNearby(self.rect) 
		entitiesnearby.extend(manager.getEntitiesNearby(self.lhitbox.rect)) # Could consolidate by making a big rect that fits all
		entitiesnearby.extend(manager.getEntitiesNearby(self.rhitbox.rect))
		entitiesnearby.extend(manager.getEntitiesNearby(self.bhitbox.rect))
		entitiesnearby.extend(manager.getEntitiesNearby(self.thitbox.rect))
		entitiesnearby.extend(manager.getEntitiesNearby(self.toprhitbox.rect))
		entitiesnearby.extend(manager.getEntitiesNearby(self.toplhitbox.rect))
		

		colliderects = []
		cielingrects = []
		climbrects = []
		if(entitiesnearby != None):
			for entity1 in entitiesnearby:
				add = True
				for entity2 in self.nocollide:
					if (entity1 == entity2):
						add = False
				if(entity1 == self.dog) or (entity1 == self.carrying) or (entity1.collides == False):
					add = False
				if(type(entity1) == platform):
					if (entity1.plat == False) and (entity1.climb == False):
						cielingrects.append(entity1.rect)
					if (entity1.climb == True):
						climbrects.append(entity1.rect)
						add = False
				if (add == True):
					colliderects.append(entity1.rect)
				add = True
					

		rHit = self.rhitbox.rect.collidelist(colliderects)
		bHit = self.bhitbox.rect.collidelist(colliderects)
		lHit = self.lhitbox.rect.collidelist(colliderects)
		toprHit = self.toprhitbox.rect.collidelist(colliderects)
		toplHit = self.toplhitbox.rect.collidelist(colliderects)
		tHit = self.thitbox.rect.collidelist(cielingrects)
		climb1 = self.bhitbox.rect.collidelist(climbrects)
		climb2 = self.thitbox.rect.collidelist(climbrects)

		if(rHit != -1):
			self.canmoveright = False
			if self.speed > 0:
				self.speed -= 1
		else:
			self.canmoveright = True

		if(lHit != -1):
			self.canmoveleft = False
			if self.speed < 0:
				self.speed += 1
		else:
			self.canmoveleft = True

		if(bHit != -1):
			self.canmovedown = False
			self.downforce = 0
		else:
			self.canmovedown = True

		if(toprHit == -1) and (rHit != -1) and (self.right == True):		#Conditions for climbing up an edge on right side
			if self.jumpforce < 3:
				self.jumpforce += .5 / manager.fpsupdate
			self.speed = 1
			self.canmovedown = False
			self.injump = True

		if(toplHit == -1) and (lHit != -1) and (self.left == True):			#Conditions for climbing up an edge on left side
			if self.jumpforce < 3:
				self.jumpforce += .5 / manager.fpsupdate
			self.speed = -1
			self.canmovedown = False
			self.injump = True
					
		if (tHit != -1):            #Can I move up?
			self.canmoveup = False
		else:
			self.canmoveup = True
			
		if(self.canmoveup != True):     
			self.jumpforce = 0
			
		if ((climb1 != -1) or (climb2 != -1)) and (self.climbing == False):
			if (self.up == True):
				self.climbing = True
			if (self.down == True) and (self.carrying == 0):
				self.climbing = True
		if (climb1 == -1) and (climb2 == -1) and (self.climbing == True):
			self.climbing = False        
		if (climb1 != -1) and (climb2 == -1) and (self.down != True):
			self.canmovedown = False
			self.downforce = 0

		manager.quadtrees[int(self.layer)].insertEntity(self)
		entity.update(self, timeElapsed, manager)

	
	@staticmethod
	def onLoad(manager, saveData):
		me = entity.onLoad(manager, saveData)
		manager.game.player = me
		manager.game.camera.setFocus(me)
		return me
		
	def draw(self, camera, screen, manager):
		entity.draw(self, camera, screen, manager)
		"""self.thitbox.draw(camera,screen)
		self.lhitbox.draw(camera, screen)
		self.rhitbox.draw(camera, screen)
		self.bhitbox.draw(camera, screen)
		self.toprhitbox.draw(camera, screen)
		self.toplhitbox.draw(camera, screen)"""

	def move(self, manager):
		self.moveBy(self.speed,0)
		
		self.lhitbox.update()
		self.rhitbox.update()
		self.bhitbox.update()
		self.thitbox.update()
		self.toprhitbox.update()
		self.toplhitbox.update()#Adjust hitboxes after move

		#If on ground, handle like this.
		if self.injump == False and self.canmovedown == False:
			if self.canmoveright == True:
				if self.right == True:
					if self.speed < 3:
						self.speed += .5 / manager.fpsupdate

			if self.canmoveleft == True:
				if self.left == True:
					if self.speed > -3:
						self.speed -= .5 / manager.fpsupdate
			if self.left == False and self.right == False:
				if self.speed > 0:
					self.speed -= .5 / manager.fpsupdate
				if self.speed < 0:
					self.speed += .5 / manager.fpsupdate
		
		#If in air, handle like tihs.
		if self.injump == True or self.canmovedown == True:
			if self.canmoveright == True:
				if self.right == True:
					if self.speed < 3:
						self.speed += .1 / manager.fpsupdate
			if self.canmoveleft == True:
				if self.left == True:
					if self.speed > -3:
						self.speed -= .1 / manager.fpsupdate
			
		#If falling, apply downforce that grows with time and stops at 4.
		if self.canmovedown == True and self.injump == False:
			if self.downforce < 4:
				self.downforce += .2 / manager.fpsupdate
				self.walljumptimer = 20
			self.rect.move_ip(0,self.downforce / manager.fpsupdate)
			self.lhitbox.update()
			self.rhitbox.update()
			self.bhitbox.update()
			self.toprhitbox.update()
			self.toplhitbox.update()
			

		#If not jumping, activate jump!
		if self.injump == False and self.canmovedown == False:
			if self.jump == True:
				self.injump = True
				
		#If jumping, apply these forces:
		if self.injump == True:
			if self.jumpforce > 0:
				self.canmovedown == False
				self.rect.move_ip(0,-self.jumpforce / manager.fpsupdate)	
				self.jumpforce -= .2 / manager.fpsupdate
				self.lhitbox.update()
				self.rhitbox.update()
				self.bhitbox.update()
				self.toprhitbox.update()
				self.toplhitbox.update()
				
		#If there is no jumpforce left, take the player out of jump mode.
		if self.jumpforce <= 0:
				self.injump = False
		
		#These two If statements make it so you slide slower while going up or down a wall
		if (self.canmoveright == False or self.canmoveleft == False) and self.injump == True:
			self.jumpforce -= .05 / manager.fpsupdate
		if (self.canmoveright == False or self.canmoveleft == False) and self.canmovedown == True:
			if self.downforce > .15:
				self.downforce -= .15 / manager.fpsupdate
		
		
		#Test if the player is able to walljump based on a timer
		if self.walljumptimer > 10:
			self.canwalljump = True
		else:
			self.canwalljump = False
			
		if self.walljumptimer < 20:
			self.walljumptimer += 1 / manager.fpsupdate
			

		#Execute the walljump if player is in position
		if self.canwalljump == True  and self.holdjump == 0:
			if (self.canmoveright == False or self.canmoveleft == False) and (self.canmovedown == True or self.injump == True):
				if self.jump == True:
					self.injump = True
					self.jumpforce = 7
					if self.canmoveright == False:
						self.speed -= 3.5 / manager.fpsupdate
					if self.canmoveleft == False:
						self.speed += 3.5 / manager.fpsupdate
		#Holdin jump key
		if self.hold == True:
			self.holdjump = 1
		else:
			self.holdjump = 0
		
		#ClimbCode
		if (self.climbing == True):
			if self.canmoveright == True:
				if self.right == True:
					self.speed = 1
				else:
					if self.speed > 0:
						self.speed = 0
			if self.canmoveleft == True:
				if self.left == True:
					self.speed = -1
				else:
					if self.speed < 0:
						self.speed = 0
			if (self.downforce > 0):
				self.downforce = 0
			if (self.up == True):
				if (self.canmoveup):
					self.rect.move_ip(0,-1.5 / manager.fpsupdate)	
			if (self.down == True):
				if (self.canmovedown):
					self.rect.move_ip(0,1.5 / manager.fpsupdate)	
			if(manager.keysdown['space']):
				self.climbing = False

